﻿namespace Kit3D.Windows.Media.Media3D
{
    using System;
    using System.Collections;
    using System.Collections.Generic;

    public class Transform3DCollection : Freezable, IList, IList<Transform3D>
    {
        private List<Transform3D> items;

        public Transform3DCollection()
        {
            this.items = new List<Transform3D>();
        }

        public Transform3DCollection(int capacity)
        {
            this.items = new List<Transform3D>(capacity);
        }

        public Transform3DCollection(IEnumerable<Transform3D> collection)
        {
            this.items = new List<Transform3D>(collection);
        }

        #region ICollection<Transform3D> Members

        public void Add(Transform3D item)
        {
            Insert(Count, item);
        }

        void item_Changed(object sender, EventArgs e)
        {
            OnChanged();
        }

        public int Add(object value)
        {
            var transform3D = (Transform3D) value;
            Add(transform3D);
            return IndexOf(transform3D);
        }

        public bool Contains(object value)
        {
            return Contains((Transform3D) value);
        }

        public void Clear()
        {
            foreach (Transform3D transform in this.items)
            {
                ListenToTransform3D(transform, false);
            }
            this.items.Clear();
            OnChanged();
        }

        public int IndexOf(object value)
        {
            return IndexOf((Transform3D) value);
        }

        public void Insert(int index, object value)
        {
            Insert(index, (Transform3D) value);
        }

        public void Remove(object value)
        {
            Remove((Transform3D) value);
        }

        public int IndexOf(Transform3D item)
        {
            return this.items.IndexOf(item);
        }

        public void Insert(int index, Transform3D item)
        {
            this.items.Insert(index, item);
            ListenToTransform3D(item, true);
            OnChanged();
        }

        private void ListenToTransform3D(Transform3D transform3D, bool listen)
        {
            if (transform3D == null)
                return;

            if (listen)
            {
                transform3D.Changed += new EventHandler(item_Changed);
            }
            else
            {
                transform3D.Changed -= new EventHandler(item_Changed);
            }
        }

        void IList<Transform3D>.RemoveAt(int index)
        {
            Remove(this[index]);
        }

        void IList.RemoveAt(int index)
        {
            Remove(this[index]);
        }

        object IList.this[int index]
        {
            get { return this[index]; }
            set { this[index] = (Transform3D) value; }
        }

        public bool Contains(Transform3D item)
        {
            return this.items.Contains(item);
        }

        public void CopyTo(Transform3D[] array, int arrayIndex)
        {
            this.items.CopyTo(array, arrayIndex);
        }

        public void CopyTo(Array array, int index)
        {
            CopyTo((Transform3D[]) array, index);
        }

        public int Count
        {
            get { return this.items.Count; }
        }

        private object _syncObject = new object();
        public object SyncRoot
        {
            get { return _syncObject; }
        }

        public bool IsSynchronized
        {
            get { return true; }
        }

        public bool IsReadOnly
        {
            get { return false; }
        }

        public bool IsFixedSize
        {
            get { return false; }
        }

        public bool Remove(Transform3D item)
        {
            bool result = this.items.Remove(item);
            if (result)
            {
                ListenToTransform3D(item, false);
                OnChanged();
            }
            return result;
        }

        #endregion

        #region IEnumerable<Transform3D> Members

        public IEnumerator<Transform3D> GetEnumerator()
        {
            return this.items.GetEnumerator();
        }

        #endregion

        #region IEnumerable Members

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        #endregion

        public Transform3D this[int index]
        {
            get
            {
                return this.items[index];
            }
            set
            {
                if (index >= Count)
                    throw new IndexOutOfRangeException();

                ListenToTransform3D(this[index], false);
                this.items[index] = value;
                ListenToTransform3D(value, true);
            }
        }
    }
}
